package com.service.totalauth.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipaySystemOauthTokenRequest;
import com.alipay.api.request.AlipayUserInfoShareRequest;
import com.alipay.api.response.AlipaySystemOauthTokenResponse;
import com.alipay.api.response.AlipayUserInfoShareResponse;
import com.service.config.utils.JsonXMLUtils;
import com.service.config.utils.ModelMapperUtil;
import com.service.config.utils.RedisUtil;
import com.service.totalauth.dao.AuthorizationUserDao;
import com.service.totalauth.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

import static com.service.config.constant.ApiUrlConstants.*;

/**
 * @author ：hjl
 * @date ：Created in 2021/12/06 19:02
 * @description：
 */
@Service
@Slf4j
public class QueryMiniProgrammeServiceImpl {
    @Resource
    RestTemplate restTemplate;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private AuthorizationUserDao authorizationUserDao;

    /**
     * 钉钉获取accessToken使用GET请求，请求参数为appKey和secret;飞书使用POST请求，飞书校验调用此方法时，这个两个参数可以传空字符串
     * 获取钉钉/飞书access_token的url
     * @param appkey 钉钉小程序的appkey
     * @param secret 钉钉小程序的secret
     * @param miniType 1:飞书小程序;2:钉钉小程序
     * @return
     */
    public String getAccessTokenUrl(String url,String appkey, String secret,Integer miniType) {
        switch (miniType)
        {
            case 1:
                url=LARK_GET_ACCESS_TOKEN;
                break;
            case 2:
                url=DING_GET_ACCESS_TOKEN.concat(appkey).concat(DING_secret).concat(secret);
                break;
            case 6:
                //qq小程序认证 appkey:AppId,secret:AppSecret
                url=QQ_GET_ACCESS_TOKEN.concat(appkey).concat(QQ_SECRET).concat(secret);
                break;
            default:
                url="";
                break;
        }
        return url;
    }

    /**
     * 与钉钉/飞书服务端交互
     * @param url 获取accessToken的url
     * @param miniType miniType 1:飞书小程序;2:钉钉小程序
     * @return
     */
    public HashMap getAccessToken (String url,Integer miniType,String appId,String secret) throws Exception {
        HashMap map = new HashMap();
        if (miniType==1)
        {
            //飞书小程序获取accessToken
            HttpHeaders requestHeaders = new HttpHeaders();
            MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
            requestHeaders.setContentType(type);
            Map map2=new HashMap();
            map2.put("app_id",appId);
            map2.put("app_secret",secret);

            HttpEntity<Map> requestEntity = new HttpEntity<Map>(map2,requestHeaders);
            ResponseEntity<JSONObject> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, JSONObject.class);
            LarkVo larkVo = ModelMapperUtil.strictMap(response.getBody(), LarkVo.class);
            if (larkVo.getCode()==null || larkVo.getCode() == 0) {
                map.put("accessToken", JsonXMLUtils.obj2json(larkVo));
            }else {
                map.put("errcode",JsonXMLUtils.obj2json(larkVo));
            }
            return map;
        }else if(miniType==2)
        {
            //钉钉小程序获取accessToken
            HttpEntity<String> requestEntity = new HttpEntity<>("");
            ResponseEntity<JSONObject> response = restTemplate.exchange(url, HttpMethod.GET, requestEntity, JSONObject.class);
            DingVo dingVo = ModelMapperUtil.strictMap(response.getBody(), DingVo.class);

            if (dingVo.getErrcode()==null || dingVo.getErrcode().equals("0")) {
                map.put("accessToken", JsonXMLUtils.obj2json(dingVo));
            }else {
                map.put("errcode",JsonXMLUtils.obj2json(dingVo));
            }
            return map;
        }else if(miniType==6)
        {
            //qq小程序获取accessToken
            HttpEntity<String> requestEntity = new HttpEntity<>("");
            ResponseEntity<JSONObject> response = restTemplate.exchange(url, HttpMethod.GET, requestEntity, JSONObject.class);
            QqVo qqVo = ModelMapperUtil.strictMap(response.getBody(), QqVo.class);

            if (qqVo.getErrcode()==null || qqVo.getErrcode().equals("0")) {
                map.put("accessToken", JsonXMLUtils.obj2json(qqVo));
            }else {
                map.put("errcode",JsonXMLUtils.obj2json(qqVo));
            }
            return map;

        }
        map.put("errcode","请求参数错误");
        return map;
    }

    /**
     * 小程序免密登录 1 飞书；2 钉钉；6 qq
     * appId和secret是qq认证使用
     * @param access_token
     * @param code
     * @param miniType
     * @return
     * @throws Exception
     */
    public HashMap code2Session(String access_token, String code,Integer miniType,String appId,String secret) throws Exception {
        HashMap map = new HashMap();
        if(miniType==1)
        {
            HttpHeaders requestHeaders = new HttpHeaders();
            MediaType type = MediaType.parseMediaType("application/json");
            requestHeaders.setContentType(type);
            requestHeaders.set("Authorization","Bearer "+access_token);
            Map params=new HashMap();
            params.put("code",code);
            params.put("token",access_token);

            HttpEntity<Map> requestEntity = new HttpEntity<Map>(params,requestHeaders);
            ResponseEntity<JSONObject> response = restTemplate.exchange(LARK_CODE2SESSION, HttpMethod.POST, requestEntity, JSONObject.class);
            LarkUserVo larkUserVo = ModelMapperUtil.strictMap(response.getBody(), LarkUserVo.class);
            if (larkUserVo.getCode() == null || larkUserVo.getCode() == 0) {
                map.put("userVo", JsonXMLUtils.obj2json(larkUserVo));
            }else {
                map.put("errcode",JsonXMLUtils.obj2json(larkUserVo));
            }
            return map;
        }else if (miniType==2)
        {
            Map params=new HashMap();
            params.put("code",code);

            HttpEntity<Map> requestEntity = new HttpEntity<Map>(params);
            ResponseEntity<JSONObject> response = restTemplate.exchange(DING_CODE2SESSION.concat(access_token), HttpMethod.POST, requestEntity, JSONObject.class);
            DingUserVo dingUserVo = ModelMapperUtil.strictMap(response.getBody(), DingUserVo.class);
            if (dingUserVo.getErrcode() == null || dingUserVo.getErrcode().equals("0")) {
                map.put("userVo", JsonXMLUtils.obj2json(dingUserVo));
            }else {
                map.put("errcode",JsonXMLUtils.obj2json(dingUserVo));
            }
            return map;
        }else if (miniType == 6)
        {
            HttpHeaders requestHeaders = new HttpHeaders();
            MediaType type = MediaType.parseMediaType("application/json");
            requestHeaders.setContentType(type);

            String url = QQ_CODE2SESSION.concat(appId).concat(QQ_SECRET).concat(secret).concat(QQ_JS_CODE).concat(code);
            HttpEntity<String> requestEntity = new HttpEntity<>(requestHeaders);

            ResponseEntity<JSONObject> response = restTemplate.exchange(url, HttpMethod.GET, requestEntity, JSONObject.class);
            QqUserVo qqUserVo = ModelMapperUtil.strictMap(response.getBody(), QqUserVo.class);
            if (qqUserVo.getErrcode() == 0) {
                map.put("userVo", JsonXMLUtils.obj2json(qqUserVo));
            }else {
                map.put("errcode",JsonXMLUtils.obj2json(qqUserVo));
            }
            return map;
        }
        map.put("errcode","请求参数错误");
        return map;
    }

    /**
     * 获取用户详情
     * @param access_token
     * @param userId
     * @param miniType
     * @return
     * @throws Exception
     */
    public HashMap getUserInfo(String access_token, String userId,Integer miniType) throws Exception {
        HashMap map = new HashMap();
        if(miniType==1)
        {
            HttpHeaders requestHeaders = new HttpHeaders();
            MediaType type = MediaType.parseMediaType("application/json");
            requestHeaders.setContentType(type);
            requestHeaders.set("Authorization","Bearer "+access_token);

            String url = LARK_GET_USERINFO.concat(userId);
            HttpEntity<String> requestEntity = new HttpEntity<>(requestHeaders);
            ResponseEntity<JSONObject> response = restTemplate.exchange(url, HttpMethod.GET, requestEntity, JSONObject.class);
            LarkUserDetailInfo larkUserDetail = ModelMapperUtil.strictMap(response.getBody(), LarkUserDetailInfo.class);
            if (larkUserDetail.getCode() == null || larkUserDetail.getCode() == 0) {
                map.put("userDetailInfo", JsonXMLUtils.obj2json(larkUserDetail));
            }else {
                map.put("errcode",JsonXMLUtils.obj2json(larkUserDetail));
            }
            return map;
        }else if(miniType==2)
        {
            String url = DING_GET_USERINFO.concat(access_token);
            Map params=new HashMap();
            params.put("userid",userId);
            params.put("language","zh_CN");

            HttpEntity<Map> requestEntity = new HttpEntity<Map>(params);
            ResponseEntity<JSONObject> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, JSONObject.class);
            DingUserDetailInfo dingUserDetailInfo = ModelMapperUtil.strictMap(response.getBody(), DingUserDetailInfo.class);
            if (dingUserDetailInfo.getErrcode() == null || dingUserDetailInfo.getErrcode() == 0) {
                map.put("userDetailInfo", JsonXMLUtils.obj2json(dingUserDetailInfo));
            }else {
                map.put("errcode",JsonXMLUtils.obj2json(dingUserDetailInfo));
            }
            return map;
        }
        map.put("errcode","请求参数错误");
        return map;
    }

    public HttpHeaders getHttpHeaders() {
        HttpHeaders requestHeaders = new HttpHeaders();
        MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
        requestHeaders.setContentType(type);
        requestHeaders.add("Accept", MediaType.APPLICATION_JSON.toString());
        return requestHeaders;
    }

    /**
     * 支付宝小程序授权登录
     * @param appId
     * @param aliPrivateKey
     * @param aliPublicKey
     * @return
     */
    public AlipaySystemOauthTokenResponse getAliAccessToken(String authCode,String appId, String aliPrivateKey, String aliPublicKey) throws AlipayApiException {
        AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do",
                appId,          // 1. 填入appid
                aliPrivateKey,      // 2. 填入私钥
                "json",
                "GBK",
                aliPublicKey,     // 3. 填入公钥
                "RSA2");
        AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
        request.setGrantType("authorization_code");
        request.setCode(authCode);    // 4. 填入前端传入的授权码authCode

        AlipaySystemOauthTokenResponse response = alipayClient.execute(request);

        /*if (response.isSuccess())
        {
            String refreshToken = response.getRefreshToken();
            request.setGrantType("refresh_token");
            request.setRefreshToken(refreshToken);
            AlipaySystemOauthTokenResponse execute = alipayClient.execute(request);
            return execute;
        }*/
        return response;
    }

    // 获取支付宝用户信息
    public AlipayUserInfoShareResponse getAliUserInfo (String accessToken,String appId,String privateKey,String publicKey) throws Exception {
        AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do",
                appId,          // 1. 填入appid
                privateKey,      // 2. 填入私钥
                "json",
                "GBK",
                publicKey,     // 3. 填入公钥
                "RSA2");
        AlipayUserInfoShareRequest request = new AlipayUserInfoShareRequest();
        AlipayUserInfoShareResponse response = alipayClient.execute(request, accessToken);
        if(response.isSuccess()){
            return response;
        }
        return null;
    }
}
